package com.quectel.grid.controller.grid;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.func.LambdaUtil;
import com.quectel.business.common.grid.GridBusiness;
import com.quectel.business.common.grid.GridEventRecordBusiness;
import com.quectel.constant.core.grid.GridConstant;
import com.quectel.constant.global.SystemConstants;
import com.quectel.core.module.grid.dto.*;
import com.quectel.core.module.grid.service.GridEventRecordService;
import com.quectel.core.module.grid.service.GridPrimaryEventService;
import com.quectel.core.module.grid.service.GridSecondaryEventService;
import com.quectel.core.module.grid.service.GridService;
import com.quectel.grid.controller.BaseController;
import com.quectel.grid.util.SessionHolder;
import com.quectel.grid.vo.grid.GridEventHandleVo;
import com.quectel.grid.vo.grid.GridEventRecordStatisticVo;
import com.quectel.grid.vo.grid.GridEventReportVo;
import com.quectel.util.common.CopyUtils;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import com.quectel.util.thread.ThreadPoolUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author caolu
 * @email louis.cao@quectel.com
 */
@RestController
@RequestMapping("gridEventRecord")
@Tag(name = "GridEventRecordController", description = "网格事件相关API")
@Slf4j
public class GridEventRecordController extends BaseController {
    public static final String ALL = "1";
    public static final String PROCESSING = "2";
    public static final String FINISHED = "3";

    private static final ThreadPoolExecutor executorService = ThreadPoolUtils.createCommonIOBoundPool("gird_api_event_record_pool");


    @DubboReference
    private GridEventRecordService gridEventRecordService;
    @DubboReference
    private GridService gridService;

    @DubboReference
    private GridPrimaryEventService gridPrimaryEventService;
    @DubboReference
    private GridSecondaryEventService gridSecondaryEventService;

    @Autowired
    private GridEventRecordBusiness gridEventRecordBusiness;
    @Autowired
    private GridBusiness gridBusiness;

    @GetMapping("queryPrimaryEvents")
    @Operation(summary = "查询租户一级全部分类")
    public Response<List<GridPrimaryEventDto>> queryPrimaryEvents() {
        Long tenantId = SessionHolder.getLoginGridUserSession().getTenantId();
        Map<String, Object> params = Request.parseParams(httpServletRequest);
        params.put(LambdaUtil.getFieldName(GridPrimaryEventDto::getTenantId), tenantId);
        return Response.<List<GridPrimaryEventDto>>ok().wrap(gridPrimaryEventService.queryList(params));
    }

    @GetMapping("querySecondaryEvent")
    @Operation(summary = "根据一级分类查询二级分类")
    public Response<List<GridSecondaryEventDto>> querySecondaryEvent(@RequestParam Long primaryId) {
        Map<String, Object> params = Request.parseParams(httpServletRequest);
        params.put(LambdaUtil.getFieldName(GridSecondaryEventDto::getPrimaryEventId), primaryId);
        return Response.<List<GridSecondaryEventDto>>ok().wrap(gridSecondaryEventService.queryList(params));
    }

    /**
     * 事件统计
     *
     * @return
     */
    @GetMapping("myStatistic")
    @Operation(summary = "事件统计")
    public Response<GridEventRecordStatisticVo> myStatistic(
            @Parameter(description = "指定网格ID") @RequestParam(required = false) Long gridId
    ) {

        DateTime now = DateTime.now();
        GridMemberDto gridMember = SessionHolder.getGridMember();
        GridDto gridDto = null;
        if (gridId != null) {
            gridDto = gridBusiness.checkGridMemberPermission(gridMember.getId(), gridId);
            if (gridDto == null) {
                return Response.error("没有查询到该网格信息");
            }
        }
        //查询日
        CompletableFuture<Integer> dayFuture = CompletableFuture.supplyAsync(
                        () -> {
                            Map<String, Object> params = new HashMap<>(2);
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getTenantId), gridMember.getTenantId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridMemberId), gridMember.getId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridId), gridId);
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getLeft(), DateUtil.format(DateUtil.beginOfDay(now), DatePattern.NORM_DATETIME_PATTERN));
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getRight(), DateUtil.format(DateUtil.endOfDay(now), DatePattern.NORM_DATETIME_PATTERN));
                            return gridEventRecordService.queryTotal(params);
                        }, executorService)
                .exceptionally(e -> {
                    return 0;
                });

        //查询周
        CompletableFuture<Integer> weekFuture = CompletableFuture.supplyAsync(
                        () -> {
                            Map<String, Object> params = new HashMap<>(2);
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getTenantId), gridMember.getTenantId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridMemberId), gridMember.getId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridId), gridId);
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getLeft(), DateUtil.format(DateUtil.beginOfWeek(now), DatePattern.NORM_DATETIME_PATTERN));
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getRight(), DateUtil.format(DateUtil.endOfWeek(now), DatePattern.NORM_DATETIME_PATTERN));
                            return gridEventRecordService.queryTotal(params);
                        }, executorService)
                .exceptionally(e -> {
                    return 0;
                });


        //查询月
        CompletableFuture<Integer> monthFuture = CompletableFuture.supplyAsync(
                        () -> {
                            Map<String, Object> params = new HashMap<>(2);
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getTenantId), gridMember.getTenantId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridMemberId), gridMember.getId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridId), gridId);
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getLeft(), DateUtil.format(DateUtil.beginOfMonth(now), DatePattern.NORM_DATETIME_PATTERN));
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getRight(), DateUtil.format(DateUtil.endOfMonth(now), DatePattern.NORM_DATETIME_PATTERN));
                            return gridEventRecordService.queryTotal(params);
                        }, executorService)
                .exceptionally(e -> {
                    return 0;
                });


        //查询年
        CompletableFuture<Integer> yearFuture = CompletableFuture.supplyAsync(
                        () -> {
                            Map<String, Object> params = new HashMap<>(2);
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getTenantId), gridMember.getTenantId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridMemberId), gridMember.getId());
                            params.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridId), gridId);
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getLeft(), DateUtil.format(DateUtil.beginOfYear(now), DatePattern.NORM_DATETIME_PATTERN));
                            params.put(GridConstant.EVENT_CREATE_DATE_SLOT_KEY_PAIR.getRight(), DateUtil.format(DateUtil.endOfYear(now), DatePattern.NORM_DATETIME_PATTERN));
                            return gridEventRecordService.queryTotal(params);
                        }, executorService)
                .exceptionally(e -> {
                    return 0;
                });

        GridEventRecordStatisticVo gridEventRecordStatisticVo = new GridEventRecordStatisticVo();
        try {
            gridEventRecordStatisticVo.setDayCount(dayFuture.get());
            gridEventRecordStatisticVo.setWeekCount(weekFuture.get());
            gridEventRecordStatisticVo.setMonthCount(monthFuture.get());
            gridEventRecordStatisticVo.setYearCount(yearFuture.get());
        } catch (InterruptedException | ExecutionException e) {
            Thread.currentThread().interrupt();
            return Response.error(e.getMessage());
        }

        return Response.<GridEventRecordStatisticVo>ok().wrap(gridEventRecordStatisticVo);
    }


    /**
     * 事件流转列表
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("eventFlowList")
    @Operation(summary = "事件流转列表,流转到对应网格的事件列表")
    public Response<Page<GridEventRecordDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize,
            @Parameter(description = "网格ID") @RequestParam(required = false) Long gridId,
            @Parameter(description = "事件名称模糊查询") @RequestParam(required = false) String queryParam,
            @Parameter(description = "非必传,默认1全部,2处理中3已处理") @RequestParam(required = false) String statusFlag

    ) {
        //校验网格权限
        GridMemberDto gridMember = SessionHolder.getGridMember();

        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        //tenantId条件
        request.put(LambdaUtil.getFieldName(GridEventRecordDto::getTenantId), SessionHolder.getGridMember().getTenantId());

        List<GridDto> myGrids = gridBusiness.getMyGrids(gridMember.getId());
        if (CollectionUtils.isEmpty(myGrids)) {
            return Response.error("该网格员没有对应网格权限");
        }

        List<Long> gridIds;
        GridDto gridDto = null;
        if (gridId != null) {
            Optional<GridDto> any = myGrids.stream().filter(grid -> gridId.equals(grid.getId())).findAny();
            if (!any.isPresent()) {
                return Response.error("没有查询到该网格信息");
            }
            gridDto = any.get();
            gridIds = Collections.singletonList(gridDto.getId());
            request.put(GridConstant.GRID_IDS, gridIds);
        } else {
            gridIds = myGrids.stream().map(GridDto::getId).collect(Collectors.toList());
            request.put(GridConstant.GRID_IDS, gridIds);
        }

        //派送事件
        request.put(GridConstant.EVENT_FLOW_TYPE, GridConstant.EVENT_FLOW_TYPE_ASSIGN);
        request.put(GridConstant.REGION_LEVEL, GridConstant.RegionLevel.GRID_LEVEL.getLevel());
        //后台创建事件或者智能发现
        List<Byte> sourceTypes = new ArrayList<>(2);
        sourceTypes.add(GridConstant.GridEventRecordSourceType.BACKGROUND_CREATION.getType());
        sourceTypes.add(GridConstant.GridEventRecordSourceType.INTELLIGENT_DISCOVERY.getType());

        request.put(GridConstant.SOURCE_TYPES, sourceTypes);

        if (StringUtils.isNotEmpty(queryParam)) {
            request.put(LambdaUtil.getFieldName(GridEventRecordDto::getEventName), queryParam);
        }

        List<Byte> statuses = new ArrayList<>();
        if (PROCESSING.equals(statusFlag)) {
            statuses.add(GridConstant.GridEventRecordStatus.TO_BE_PROCESSED.getStatus());
            statuses.add(GridConstant.GridEventRecordStatus.TO_BE_FINISHED.getStatus());
            statuses.add(GridConstant.GridEventRecordStatus.REJECTED.getStatus());
            request.put(SystemConstants.STATUSES, statuses);

        } else if (FINISHED.equals(statusFlag)) {
            statuses.add(GridConstant.GridEventRecordStatus.FINISHED.getStatus());
            request.put(SystemConstants.STATUSES, statuses);
        }

        int total = gridEventRecordService.queryTotal(request.getParams());

        List<GridEventRecordDto> list = null;
        if (total > 0) {
            list = gridEventRecordService.queryList(request.getParams());
        } else {
            list = new ArrayList<>();
        }

        Page<GridEventRecordDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<GridEventRecordDto>>ok().wrap(page);
    }


    /**
     * 我的发起事件列表
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("myList")
    @Operation(summary = "本级创建列表")
    public Response<Page<GridEventRecordDto>> myList(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize,
            @Parameter(description = "网格ID") @RequestParam(required = false) Long gridId,
            @Parameter(description = "事件名称模糊查询") @RequestParam(required = false) String queryParam,
            @Parameter(description = "非必传,默认1全部,2处理中3已处理") @RequestParam(required = false) String statusFlag

    ) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        //创建层级是网格员
        GridMemberDto gridMember = SessionHolder.getLoginGridUserSession().getGridMember();
        List<GridDto> myGrids = gridBusiness.getMyGrids(gridMember.getId());
        if (CollectionUtils.isEmpty(myGrids)) {
            return Response.error("该网格员没有对应网格权限");
        }

        GridDto gridDto = null;
        if (gridId != null) {
            Optional<GridDto> any = myGrids.stream().filter(grid -> gridId.equals(grid.getId())).findAny();
            if (!any.isPresent()) {
                return Response.error("没有查询到该网格信息");
            }
            gridDto = any.get();
        }

        request.put(LambdaUtil.getFieldName(GridEventRecordDto::getCreatorLevel), GridConstant.RegionLevel.GRID_LEVEL.getLevel());
        request.put(LambdaUtil.getFieldName(GridEventRecordDto::getGridMemberId), gridMember.getId());
        //上报事件
        request.put(LambdaUtil.getFieldName(GridEventRecordDto::getSourceType), GridConstant.GridEventRecordSourceType.REPORT.getType());

        if (gridDto != null) {
            //创建层级是网格 创建人是对应的登录人员
            request.put(LambdaUtil.getFieldName(GridEventRecordDto::getCreatorUniqueFlag), String.valueOf(gridId));
        } else {
            List<String> grids = myGrids.stream().map(value -> String.valueOf(value.getId())).collect(Collectors.toList());
            //创建层级是网格 创建人是对应的登录人员
            request.put(GridConstant.CREATOR_UNIQUE_FLAGS, grids);
        }

        if (StringUtils.isNotEmpty(queryParam)) {
            request.put(LambdaUtil.getFieldName(GridEventRecordDto::getEventName), queryParam);
        }

        List<Byte> statuses = new ArrayList<>();
        if (PROCESSING.equals(statusFlag)) {
            statuses.add(GridConstant.GridEventRecordStatus.TO_BE_PROCESSED.getStatus());
            statuses.add(GridConstant.GridEventRecordStatus.TO_BE_FINISHED.getStatus());
            statuses.add(GridConstant.GridEventRecordStatus.REJECTED.getStatus());
            request.put(SystemConstants.STATUSES, statuses);
        } else if (FINISHED.equals(statusFlag)) {
            statuses.add(GridConstant.GridEventRecordStatus.FINISHED.getStatus());
            request.put(SystemConstants.STATUSES, statuses);
        }

        int total = gridEventRecordService.queryTotal(request.getParams());

        List<GridEventRecordDto> list = null;
        if (total > 0) {
            list = gridEventRecordService.queryList(request.getParams());
        } else {
            list = new ArrayList<>();
        }

        Page<GridEventRecordDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<GridEventRecordDto>>ok().wrap(page);
    }

    /**
     * 事件上报
     *
     * @param gridEventReportVo
     * @return
     */
    @PostMapping("report")
    @Operation(summary = "事件上报,上级处置事件上报和自行")
    public Response<Object> report(@RequestBody GridEventReportVo gridEventReportVo) {

        GridMemberDto gridMember = SessionHolder.getLoginGridUserSession().getGridMember();

        GridEventRecordDto gridEventRecordDto = CopyUtils.copyObj(gridEventReportVo, GridEventRecordDto.class);

        gridEventRecordBusiness.checkEventParams(gridEventRecordDto, gridMember);

        GridDto gridDto = gridService.selectById(gridEventRecordDto.getGridId());

        GridEventRecordDto recordDto = gridEventRecordBusiness.genReportEvent(gridEventRecordDto, gridDto, gridMember);

        gridEventRecordService.saveOrUpdateWithLog(recordDto);

        return Response.ok();
    }


    /**
     * 事件反馈
     *
     * @param handleVo
     * @return
     */
    @PostMapping("handleEvent")
    @Operation(summary = "事件处置")
    public Response<Object> handleEvent(@RequestBody GridEventHandleVo handleVo) {

        GridMemberDto gridMember = SessionHolder.getLoginGridUserSession().getGridMember();
        GridEventRecordDto gridEventRecordDto = gridEventRecordService.selectById(handleVo.getGridEventRecordId());
        if (gridEventRecordDto == null) {
            return Response.error("事件不存在");
        }

        //租户校验
        if (!gridMember.getTenantId().equals(gridEventRecordDto.getTenantId())) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        //是否超时
        if (gridEventRecordDto.getDeadline() != null && gridEventRecordDto.getDeadline().before(DateTime.now())) {
            return Response.error("事件逾期，无法反馈");
        }

        GridDto gridDto = gridBusiness.checkGridMemberPermission(gridMember.getId(), gridEventRecordDto.getGridId());
        if (gridDto == null) {
            return Response.error("没有查询到该网格信息");
        }
        //不在当前节点
        if (!String.valueOf(gridEventRecordDto.getGridId()).equals(gridEventRecordDto.getCurrentCode()) || !gridEventRecordDto.getCurrentLevel().equals(GridConstant.RegionLevel.GRID_LEVEL.getLevel())) {
            return Response.error("没有操作权限");
        }

        //如果不是自己上报的,不允许操作
        if (gridEventRecordDto.getGridMemberId() != null && !gridEventRecordDto.getGridMemberId().equals(gridMember.getId())) {
            return Response.error("没有操作权限");
        }
        //驳回或者待处理状态可以操作
        if (!GridConstant.GridEventRecordStatus.REJECTED.getStatus().equals(gridEventRecordDto.getStatus())
                && !GridConstant.GridEventRecordStatus.TO_BE_PROCESSED.getStatus().equals(gridEventRecordDto.getStatus())) {
            return Response.error("当前状态不可以反馈");
        }

        gridEventRecordDto.setGridMemberId(gridMember.getId());
        gridEventRecordDto.setStatus(GridConstant.GridEventRecordStatus.TO_BE_FINISHED.getStatus());
        gridEventRecordDto.setEditor(gridMember.getName());
        gridEventRecordDto.setEditTime(DateTime.now());
        //处理节点为上级
        gridEventRecordDto.setCurrentLevel(GridConstant.RegionLevel.VILLAGE_LEVEL.getLevel());
        gridEventRecordDto.setCurrentCode(String.valueOf(gridEventRecordDto.getVillageId()));

        //生成日志
        List<GridEventRecordLogDto> logs = new ArrayList<>();
        GridEventRecordLogDto log = new GridEventRecordLogDto();
        log.setHandleLevel(GridConstant.RegionLevel.GRID_LEVEL.getLevel());
        log.setHandleStatus(GridConstant.GridEventRecordLogType.FEEDBACK.getStatus());
        log.setHandleUnitName(gridDto.getVillage() != null ? gridDto.getVillage().getName() + gridDto.getName() : gridDto.getName());
        log.setHandleUserType(GridConstant.GridEventRecordPersonType.GRID_MEMBER.getType());
        log.setHandleUserId(gridMember.getId());
        log.setHandleDesc("由" + gridMember.getName() + "申请办结");
        log.setHandleDetail(handleVo.getHandleDetail());
        log.setHandlePicturesJson(handleVo.getHandlePicturesJson());
        log.setCreateTime(DateTime.now());
        logs.add(log);
        gridEventRecordDto.setLogList(logs);
        gridEventRecordService.saveOrUpdateWithLog(gridEventRecordDto);

        return Response.ok();
    }


    /**
     * 详情
     *
     * @param id
     * @return
     */
    @GetMapping("info/{id}")
    @Operation(summary = "查询单条记录")
    public Response<GridEventRecordDto> info(@PathVariable("id") Long id) {
        GridMemberDto gridMember = SessionHolder.getGridMember();


        Map<String, Object> params = new HashMap<>();
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        params.put(LambdaUtil.getFieldName(GridEventRecordDto::getTenantId), gridMember.getTenantId());

        if (gridEventRecordService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        GridEventRecordDto gridEventRecordDto = gridEventRecordService.selectById(id);

        List<GridDto> myGrids = gridBusiness.getMyGrids(gridMember.getId());
        List<Long> collect = myGrids.stream().map(GridDto::getId).collect(Collectors.toList());

        //如果网格ID为空 或者网格员管理的网格不包含该区域 则不允许查看详情
        if (gridEventRecordDto.getGridId() == null || !collect.contains(gridEventRecordDto.getGridId())) {
            return Response.error("没有操作权限");
        }

        return Response.<GridEventRecordDto>ok().wrap(gridEventRecordDto);
    }


}
